#include "types.h"
#include "param.h"
#include "memlayout.h"
#include "riscv.h"
#include "defs.h"
#include "sbi.h"
#include "dtb.h"

volatile static int main_hartid = -1;

void timerinit();
void start_other_hart();

// entry.S 跳转到main(S模式)
void main(int hartid, uint64 dtb_addr) {
  // 初始化每个CPU的S模式寄存器
  // 暂时关闭分页
  w_satp(0);
  // 开启S模式中断
  w_sie(r_sie() | SIE_SEIE | SIE_STIE | SIE_SSIE);
  // 保存hartid到tp寄存器
  w_tp(hartid);
  // 第一个启动的核作为主核
  if(main_hartid == -1){
    dtb_init((void *)dtb_addr);
    dtb_parse();
    drivers_init();

    consoleinit();
    printfinit();
    // dtb_print_devices();
    print_logo();
    kinit();         // 初始化物理页分配器
    kvminit();       // 创建内核页表
    kvminithart();   // 开启分页
    procinit();      // 初始化进程表
    trapinit();
    trapinithart();  // 初始化trap处理函数
    plicinit();      // 设置中断控制器
    plicinithart();
    timerinit();     // 设置定时器
    binit();         // 初始化磁盘缓冲区
    iinit();         // 初始化inode表
    fileinit();      // 初始化文件表
    virtio_disk_init(); // 初始化虚拟磁盘
    userinit();      // 初始化第一个用户进程
    start_other_hart();  // 启动从核
    __sync_synchronize();
    main_hartid = hartid;
  } else {
    __sync_synchronize();
    printf("hart %d starting\n", hartid);
    kvminithart();    // turn on paging
    trapinithart();   // install kernel trap vector
    plicinithart();   // ask PLIC for device interrupts
    timerinit();      // ask for clock interrupts using SBI
  }

  scheduler();    
}

// 使用SBI调用设置定时器中断，底层会配置机器模式寄存器
void timerinit() {
  sbi_set_timer(r_time() + 200000);
}
// 启动从核
void start_other_hart() {
  for(int i = 0; i < NCPU; i++) {
    if(i != main_hartid) {
      sbi_hart_start(i, (uint64)KERNTEXTBASE, 0);
    }
  }
}
